package com.xnx3.j2ee.system.responseBody;

import org.springframework.core.MethodParameter;
import org.springframework.http.MediaType;
import org.springframework.http.server.ServerHttpRequest;
import org.springframework.http.server.ServerHttpResponse;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.xnx3.j2ee.util.ConsoleUtil;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

/**
 * 针对json接口的 ResponseBody 的json返回值拦截处理
 * @author: 管雷鸣
 */
@ControllerAdvice
public class WMResponseBody implements ResponseBodyAdvice {
    @Override
    public Object beforeBodyWrite(Object body, MethodParameter arg1,
                                  MediaType arg2, Class arg3, ServerHttpRequest request,
                                  ServerHttpResponse arg5) {
    	ResponseBodyManage manage = (ResponseBodyManage) body.getClass().getAnnotation(ResponseBodyManage.class);
    	if(manage == null) {
    		//没有这个注解标注，那么不过滤什么字段，原样返回
    		return body;
    	}
    	
		//如果没有要忽略的字段，也不需要给null重新赋值，那么将之原样返回
		if((manage.ignoreField() == null || manage.ignoreField().length < 1) && manage.nullSetDefaultValue() == false) {
			return body;
		}
    	
		/***** nullSetDefaultValue 起作用 ******/
		String bodyStr;
		if(manage.nullSetDefaultValue()) {
			bodyStr = com.alibaba.fastjson.JSONObject.toJSONString(body,
					SerializerFeature.WriteMapNullValue,
					SerializerFeature.WriteNullListAsEmpty , // List字段如果为null,输出为[],而非null
					SerializerFeature.WriteNullStringAsEmpty, //字符类型字段如果为null,输出为”“,而非null
					SerializerFeature.WriteNullNumberAsZero, //数值字段如果为null,输出为0,而非null
					SerializerFeature.WriteNullBooleanAsFalse ,//Boolean字段如果为null,输出为false,而非null
					SerializerFeature.SkipTransientField , //类中的Get方法对应的Field是transient，序列化时将会被忽略。默认为true
					SerializerFeature.DisableCircularReferenceDetect, //消除对同一对象循环引用的问题，默认为false
					SerializerFeature.WriteEnumUsingName
					);
			bodyStr = bodyStr.replaceAll("\":null", "\":{}");	//将所有空直接转化为 {} 空对象
		}else {
			bodyStr = com.alibaba.fastjson.JSONObject.toJSONString(body, SerializerFeature.WriteMapNullValue);
		}
		
		/***** ignoreField 起作用 ******/
		if((manage.ignoreField() != null && manage.ignoreField().length > 0)) {
			try {
				JSONObject json = net.sf.json.JSONObject.fromObject(bodyStr);
		    	jsonDispose(json, manage.ignoreField());
		    	bodyStr = json.toString();
			} catch (Exception e) {
				ConsoleUtil.error(bodyStr);
				e.printStackTrace();
				return bodyStr;
			}
		}
		
		com.alibaba.fastjson.JSONObject returnJson = (com.alibaba.fastjson.JSONObject) com.alibaba.fastjson.JSONObject.parseObject(bodyStr);
    	return returnJson;
    }

    @Override
    public boolean supports(MethodParameter arg0, Class arg1) {
        return true;
    }
    
    public static void jsonDispose(Object obj, String[] ignoreFields) {
    	if(obj == null) {
    		return;
    	}
    	if(obj instanceof JSONObject) {
    		//如果是json对象，那么继续向下遍历
    		JSONObject json = (JSONObject)obj;
    		
    		JSONArray namesArray = json.names();
    		
    		for(int i=0; i<namesArray.size(); i++) {
    			String key = namesArray.getString(i);
        		Object subObj = json.get(key);
        		if(isJsonObject(subObj)) {
        			//是json，继续向下遍历
        			jsonDispose(subObj, ignoreFields);
        		}else {
        			//不是json了，那么判断key是否在忽略的字段里面
        			if(isIgnoreField(key, ignoreFields)) {
        				//要删除
//        				System.out.println("delete  --- "+key);
        				json.remove(key);
        			}
        		}
        	}
    	}else if(obj instanceof JSONArray) {
    		//如果是json数组，那么继续往下遍历
    		JSONArray jsonArray = (JSONArray)obj;
    		for (int i = 0; i < jsonArray.size(); i++) {
    			Object subObj = jsonArray.get(i);
    			if(isJsonObject(subObj)) {
        			//是json，继续向下遍历
        			jsonDispose(subObj, ignoreFields);
        		}else {
        			//不是json了，那么忽略之
        			
        		}
			}
    	}
    	
    }
    
    /**
     * 判断当前key是否在忽略字段之内
     * @param key json返回值中key值
     * @param ignoreFields 忽略的字段，数组形式，每个忽略字段都是数组中的一个
     * @return 如果key是在忽略字段之内，那返回true，如果不是忽略字段，返回false
     */
    public static boolean isIgnoreField(String key, String[] ignoreFields) {
    	for (int i = 0; i < ignoreFields.length; i++) {
    		if(ignoreFields[i].equalsIgnoreCase(key)) {
    			return true;
    		}
		}
    	return false;
    }
    
    /**
     * 判断某个对象是否是json对象或者json数组
     * @param obj 对象
     * @return 是，则返回true，不是json对象或数组，返回false
     */
    public static boolean isJsonObject(Object obj) {
    	if(obj == null) {
    		return false;
    	}
    	if(obj instanceof JSONObject || obj instanceof JSONArray) {
    		//json对象或数组
    		return true;
    	}else {
    		return false;
    	}
    }
    
    public static boolean isDelete(Object obj) {
    	if(obj instanceof JSONObject || obj instanceof JSONArray) {
    		//json对象或数组
    		return false;
    	}else{
    		//正常数据，判断是否是删除的字段
    		return false;
    	}
    }
    
    public static void main(String[] args) {
		String bodyStr = "{\"info\":\"登录成功\",\"parentAgency\":{\"address\":\"山东潍坊（您可通过代理后台agency修改此处的信息）\",\"addtime\":1512818402,\"allowCreateSubAgency\":0,\"allowSubAgencyCreateSub\":0,\"expiretime\":2143123200,\"id\":51,\"money\":0,\"name\":\"管雷鸣&#40;代理后台agency修改&#41;\",\"parentId\":0,\"phone\":\"333333333\",\"qq\":\"921153866\",\"siteSize\":99999999,\"state\":1,\"userid\":392,\"version\":4},\"result\":0,\"token\":\"a120904b-b019-4018-8504-23b0b9a05e0c\",\"user\":{\"authority\":\"1\",\"currency\":0,\"email\":\"\",\"freezemoney\":0,\"head\":\"70877108e0684e1d9586f327eb5aafb5.png\",\"id\":243,\"isfreeze\":0,\"lastip\":\"127.0.0.1\",\"lasttime\":1650682777,\"money\":0,\"nickname\":\"客服小红\",\"password\":\"0c5a0883e40a2a6ad84a42eab27519e6\",\"phone\":\"\",\"referrerid\":392,\"regip\":\"218.56.88.231\",\"regtime\":1488446743,\"salt\":\"6922\",\"sex\":\"\",\"sign\":\"\",\"username\":\"wangzhan\",\"version\":254}}";
		System.out.println(bodyStr);
		
		String ignoreField = "password,salt,version,currency,nickname,authority,money,head,isfreeze,sex,sign,freezemoney,referrerid";
		/***** ignoreField 起作用 ******/
//		try {
//			JSONObject json = net.sf.json.JSONObject.fromObject(bodyStr);
//	    	jsonDispose(json, ignoreField);
//	    	bodyStr = json.toString();
//		} catch (Exception e) {
//			ConsoleUtil.error(bodyStr);
//			e.printStackTrace();
//			return bodyStr;
//		}
//		
//		com.alibaba.fastjson.JSONObject returnJson = (com.alibaba.fastjson.JSONObject) com.alibaba.fastjson.JSONObject.parseObject(bodyStr);
//    	return returnJson;
    }
}
